#include<pthread.h>
#include<semaphore.h>
#include<vector>

static int defaultvalue=5;

template<class T>
class Ringqueue{
public:
    Ringqueue(int cp=defaultvalue):q_(cp),cpos_(0),ppos_(0),cp_(cp)
    {
        pthread_mutex_init(&cm_,nullptr);
        pthread_mutex_init(&pm_,nullptr);
        sem_init(&data_sem_,0,0);
        sem_init(&space_sem_,0,cp);
    }

    void push(T n)
    {
        sem_wait(&space_sem_);
        //将信号量放到加锁外面提高并发度
        pthread_mutex_lock(&pm_);
        ppos_=ppos_%q_.size();
        q_[ppos_]=n;
        ppos_++;
        pthread_mutex_unlock(&pm_);

        sem_post(&data_sem_);
    }

    T pop()
    {
        sem_wait(&data_sem_);

        pthread_mutex_lock(&pm_);
        cpos_=cpos_%q_.size();
        T re=q_[cpos_];
        cpos_++;
        pthread_mutex_unlock(&pm_);

        sem_post(&space_sem_);

        return re;
    }

    ~Ringqueue()
    {
        pthread_mutex_destroy(&cm_);
        pthread_mutex_destroy(&pm_);
        sem_destroy(&data_sem_);
        sem_destroy(&space_sem_);
    }

private:
    pthread_mutex_t cm_;
    pthread_mutex_t pm_;
    sem_t data_sem_;
    sem_t space_sem_;
    std::vector<T> q_;
    int cpos_;
    int ppos_;
    int cp_;
};